package i18n_manager

import (
	"embed"
	"errors"
	"io/fs"
	"strings"

	"github.com/BurntSushi/toml"
	"github.com/nicksnyder/go-i18n/v2/i18n"
	"golang.org/x/text/language"
)

type I18nManager struct {
	bundle       *i18n.Bundle
	localizer    *i18n.Localizer
	defaultLang  string
	fallbackLang string
}

type BundleHandleFunc func(bundle *i18n.Bundle) error

func NewI18nManager(defaultLang, fallbackLang string, handleFuncs ...BundleHandleFunc) (*I18nManager, error) {
	bundle := i18n.NewBundle(language.Make(defaultLang))
	for _, handleFunc := range handleFuncs {
		if err := handleFunc(bundle); err != nil {
			return nil, err
		}
	}
	localizer := i18n.NewLocalizer(bundle, defaultLang, fallbackLang)
	return &I18nManager{
		bundle:       bundle,
		localizer:    localizer,
		defaultLang:  defaultLang,
		fallbackLang: fallbackLang,
	}, nil
}

func (i *I18nManager) LoadTomlMessageFileFs(tomlFs embed.FS) error {
	i.bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
	return fs.WalkDir(tomlFs, ".", func(path string, d fs.DirEntry, err error) error {
		if err != nil {
			return err
		}
		if !d.IsDir() && strings.HasSuffix(path, ".toml") {
			if _, err := i.bundle.LoadMessageFileFS(tomlFs, path); err != nil {
				return err
			}
		}
		return err
	})
}

func (i *I18nManager) SetLanguage(lang ...string) {
	langs := make([]string, 0, len(lang)+2)
	for _, s := range lang {
		if s == "" {
			continue
		}
		langs = append(langs, s)
	}
	langs = append(langs, i.defaultLang, i.fallbackLang)
	i.localizer = i18n.NewLocalizer(i.bundle, langs...)
}

func (i *I18nManager) T(msgId string, tmplData map[string]any) (string, error) {
	if i == nil || i.localizer == nil {
		return "", errors.New("i18n manager is not initialized")
	}
	return i.localizer.Localize(&i18n.LocalizeConfig{
		MessageID:    msgId,
		TemplateData: tmplData,
	})
}

func (i *I18nManager) Tn(msgId string, count int64, tmplData map[string]any) (string, error) {
	if i == nil || i.localizer == nil {
		return "", errors.New("i18n manager is not initialized")
	}
	return i.localizer.Localize(&i18n.LocalizeConfig{
		MessageID:    msgId,
		TemplateData: tmplData,
		PluralCount:  count,
	})
}
